﻿using General.Core.Config;
using General.Core.Data;
using General.Entities.Data;
using General.Entities.Models;
using General.Entities.ViewData.Article;
using General.Entities.ViewData.Template;
using General.Services.Article;
using General.Services.DiyPage;
using General.Services.Link;
using General.Services.Navigation;
using General.Services.Slider;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Caching.Memory;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace General.Services.Template
{
    public class TemplateService : ITemplateService
    {
        private readonly IWebHostEnvironment environment;
        private readonly IArticleService articleService;
        private readonly IRepository<tc_sysconfig> tc_SysconfigRepository;
        private readonly INavigationService navigationService;
        private readonly ISliderService sliderService;
        private readonly ILinkService linkService;
        private readonly IMemoryCache memoryCache;

        public TemplateService(IWebHostEnvironment environment,
            IArticleService articleService,
            IRepository<tc_sysconfig> tc_sysconfigRepository,
            INavigationService navigationService,
            ISliderService sliderService,
             ILinkService linkService,
             IMemoryCache memoryCache)
        {
            this.environment = environment;
            this.articleService = articleService;
            tc_SysconfigRepository = tc_sysconfigRepository;
            this.navigationService = navigationService;
            this.sliderService = sliderService;
            this.linkService = linkService;
            this.memoryCache = memoryCache;
        }

        /// <summary>
        /// 获取模板信息列表
        /// </summary>
        /// <returns></returns>
        public AdminResult GetTemplatePages()
        {
            AdminResult result = new AdminResult();
            var data = WebSiteTemplateConfig.GetTemplatePages();
            var list = new List<TemplatePage>();
            foreach (var item in data)
            {
                list.Add(new TemplatePage() { htmlContent="", name = item.name, remark=item.remark });
            }
            result.count = list.Count();
            result.data = list;
            result.code = 0;
            return result;

        }

        /// <summary>
        /// 获取模板文件夹列表
        /// </summary>
        /// <returns></returns>
        public List<TemplateModel> GetTemplateList()
        {
            List<TemplateModel> list = new List<TemplateModel>();

            DirectoryInfo localdir = new DirectoryInfo(environment.WebRootPath + WebSiteConfig.WEBSITE_TEMPLATENAME_PATH);

            DirectoryInfo[] dirList = localdir.GetDirectories();
            foreach (var item in dirList)
            {
                var temp = new TemplateModel();
                temp.name = item.Name;
                var selectName = memoryCache.Get<string>(WebSiteConfig.WEBSITE_TEMPLATENAME_STRING);
                temp.isChecked = false;
                if (item.Name == selectName)
                {
                    temp.isChecked = true;
                }
                list.Add(temp);
            }

            return list;
        }


        /// <summary>
        /// 设置模板文件
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public async Task<int> SetTemplateName(string name)
        {
            var model = await tc_SysconfigRepository.GetAsync(x => x.code == WebSiteConfig.WEBSITE_TEMPLATENAME_STRING);
            model.value = name;
            memoryCache.Set(WebSiteConfig.WEBSITE_TEMPLATENAME_STRING, name);
            return await tc_SysconfigRepository.UpdateAsync(model);
        }


        /// <summary>
        /// 清除模板缓存
        /// </summary>
        /// <returns></returns>
        public void ClearTemplateCache()
        {
            //var list = WebSiteTemplateConfig.GetTemplatePages();
            //foreach (var item in list)
            //{
            //    memoryCache.Remove(item.name);
            //}
            WebSiteTemplateConfig.Site_Template_Index_Info.htmlContent = "";
            WebSiteTemplateConfig.Site_Template_Header_Info.htmlContent = "";
            WebSiteTemplateConfig.Site_Template_Main_Info.htmlContent = "";
            WebSiteTemplateConfig.Site_Template_Search_Info.htmlContent = "";
            WebSiteTemplateConfig.Site_Template_Footer_Info.htmlContent = "";
            WebSiteTemplateConfig.Site_Template_Detail_Info.htmlContent = "";
            WebSiteTemplateConfig.Site_Template_List_Info.htmlContent = "";
            memoryCache.Remove(WebSiteConfig.SYSTEM_NAVIGATIONMEMORYKEY_STRING);
        }


        /// <summary>
        /// 清除数据缓存
        /// </summary>
        /// <returns></returns>
        public async Task ClearDataCache()
        {
            var WebSite_UniqueIdentification = memoryCache.Get("WebSite_UniqueIdentification").ToString();
            var keys = RedisHelper.Keys(WebSite_UniqueIdentification + WebSiteConfig.Redis_Article_Key + "*");
            await RedisHelper.DelAsync(keys);
            memoryCache.Remove(WebSiteConfig.WebSite_Detail_NewArticle_Key);

            var keys2 = RedisHelper.Keys(WebSite_UniqueIdentification + WebSiteConfig.Redis_ArticleListInfo_Key + "*");
            await RedisHelper.DelAsync(keys2);

            var keys3 = RedisHelper.Keys(WebSite_UniqueIdentification + WebSiteConfig.Redis_List_Article_Key + "*");
            await RedisHelper.DelAsync(keys3);
            memoryCache.Remove(WebSiteConfig.WebSite_List_AllCate_Key);
        }



        /// <summary>
        /// 清除主页缓存
        /// </summary>
        /// <returns></returns>
        public void ClearMainCache()
        {
            memoryCache.Remove(WebSiteConfig.SYSTEM_SLIDERMEMORYKEY_STRING);
            memoryCache.Remove(WebSiteConfig.SYSTEM_LINKMEMORYKEY_STRING);
            memoryCache.Remove(WebSiteConfig.WebSite_Main_NewArticle_Key);
        }

        /// <summary>
        /// 获取模板渲染后html内容
        /// </summary>
        /// <param name="templateName"></param>
        /// <returns></returns>
        public async Task<string> GetPageHtmlContent(string templateName, string parm = "")
        {
            var indexHtml = WebSiteTemplateConfig.Site_Template_Index_Info.htmlContent;
            var headerHtml = WebSiteTemplateConfig.Site_Template_Header_Info.htmlContent;
            var footerHtml = WebSiteTemplateConfig.Site_Template_Footer_Info.htmlContent;

            if (templateName == WebSiteTemplateConfig.Site_Template_Main_Info.name)
            {
                indexHtml = indexHtml.Replace("@Title",memoryCache.Get("SEO_Index_Title").ToString()).Replace("@KeyWords", memoryCache.Get("SEO_Index_KeyWords").ToString()).Replace("@Description", memoryCache.Get("SEO_Index_Description").ToString());
                var mainHtml = WebSiteTemplateConfig.Site_Template_Main_Info.htmlContent;
                mainHtml = await LoadMainSliderInfo(mainHtml);
                mainHtml = await LoadMainLinkInfo(mainHtml);
                mainHtml = await LoadIndexNewArticleInfo(mainHtml);
                indexHtml = indexHtml.Replace("@Section_Main", mainHtml);
            }



            //logo设置
            headerHtml = headerHtml.Replace("@Logo", memoryCache.Get("WebSite_Logo").ToString());
            //导航菜单根据缓存策略获取
            headerHtml = await LoadHeaderNavigationInfo(headerHtml);
            //顶部
            indexHtml = indexHtml.Replace("@Section_Header", headerHtml);

            //底部
            footerHtml = footerHtml.Replace("@Copyright", memoryCache.Get("WebSite_Copyright").ToString());
            indexHtml = indexHtml.Replace("@Section_Footer", footerHtml);
            return indexHtml;
        }


        /// <summary>
        /// 加载主页 最新信息
        /// </summary>
        /// <param name="html"></param>
        /// <returns></returns>
        public async Task<string> LoadIndexNewArticleInfo(string html)
        {
            if (WebSiteTemplateConfig.WebSite_OpenMainCache)
            {
                var memoryDataInfo = memoryCache.Get(WebSiteConfig.WebSite_Main_NewArticle_Key);
                if (memoryDataInfo != null)
                {
                    return Regex.Replace(html, "@Article_Start[.\\s\\S]*@Article_End", memoryDataInfo.ToString(), RegexOptions.IgnoreCase);
                }
            }

            StringBuilder OutHtml = new StringBuilder();
            MatchCollection mc = Regex.Matches(html, "(?<=(@Article_Start))[.\\s\\S]*?(?=(@Article_End))");
            foreach (Match m in mc)
            {
                var arr = m.Value.Split(",", StringSplitOptions.RemoveEmptyEntries);
                var parmList = new List<string>() { "", "" };
                for (int i = 0; i < arr.Length; i++)
                {
                    parmList[i] = arr[i];
                }
                List<SimpleArticleInfo> articleInfo = await articleService.GetNewList(Convert.ToInt32(parmList[1].Trim()), 1);

                foreach (var item in articleInfo)
                {
                    var temp = parmList[0].Replace("@Title", item.title).Replace("@Id", item.id.ToString()).Replace("@Thumb", item.thumb).Replace("@AuthorName", item.username).Replace("@AuthorImage", item.userImage).Replace("@CateName", item.cateName).Replace("@CateId", item.cateId.ToString()).Replace("@Time", item.creatTime).Replace("@Hits", item.hits.ToString());
                    OutHtml.Append(temp);
                }



                if (WebSiteTemplateConfig.WebSite_OpenMainCache)
                    memoryCache.Set(WebSiteConfig.WebSite_Main_NewArticle_Key, OutHtml);
                break;
            }
			if (mc.Count==0)
            {
                return html;
            }
            return Regex.Replace(html, "@Article_Start[.\\s\\S]*@Article_End", OutHtml.ToString(), RegexOptions.IgnoreCase);
        }


        /// <summary>
        /// 加载主页友情链接
        /// </summary>
        /// <param name="html"></param>
        /// <returns></returns>
        public async Task<string> LoadMainLinkInfo(string html)
        {
            if (WebSiteTemplateConfig.WebSite_OpenMainCache)
            {
                var memoryDataInfo = memoryCache.Get(WebSiteConfig.SYSTEM_LINKMEMORYKEY_STRING);
                if (memoryDataInfo != null)
                {
                    return Regex.Replace(html, "@Link_Start[.\\s\\S]*@Link_End", memoryDataInfo.ToString(), RegexOptions.IgnoreCase);
                }
            }
            List<tc_link> linkInfo = await linkService.GetIsUseList();
            StringBuilder OutHtml = new StringBuilder();
            MatchCollection mc = Regex.Matches(html, "(?<=(@Link_Start))[.\\s\\S]*?(?=(@Link_End))");
            foreach (Match m in mc)
            {
                foreach (var item in linkInfo)
                {
                    OutHtml.Append(m.Value.Replace("@Name", item.name).Replace("@Url", item.url).Replace("@Nofollow", item.nofollow == 1 ? "rel=\"nofollow\"":""));
                }
                if (WebSiteTemplateConfig.WebSite_OpenMainCache)
                    memoryCache.Set(WebSiteConfig.SYSTEM_LINKMEMORYKEY_STRING, OutHtml);
                break;
            }
			if (mc.Count==0)
            {
                return html;
            }
            return Regex.Replace(html, "@Link_Start[.\\s\\S]*@Link_End", OutHtml.ToString(), RegexOptions.IgnoreCase);
        }


        /// <summary>
        /// 加载主页图片轮播
        /// </summary>
        /// <returns></returns>
        public async Task<string> LoadMainSliderInfo(string html)
        {
            if (WebSiteTemplateConfig.WebSite_OpenMainCache)
            {
                var memoryDataInfo = memoryCache.Get(WebSiteConfig.SYSTEM_SLIDERMEMORYKEY_STRING);
                if (memoryDataInfo != null)
                {
                    return Regex.Replace(html, "@Slider_Start[.\\s\\S]*@Slider_End", memoryDataInfo.ToString(), RegexOptions.IgnoreCase);
                }
            }
            List<tc_slider> sliderInfo = await sliderService.GetIsUseList();
            StringBuilder OutHtml = new StringBuilder();
            MatchCollection mc = Regex.Matches(html, "(?<=(@Slider_Start))[.\\s\\S]*?(?=(@Slider_End))");
            foreach (Match m in mc)
            {
                foreach (var item in sliderInfo)
                {
                    OutHtml.Append(m.Value.Replace("@Image",item.img).Replace("@Url", item.url).Replace("@Title",item.title));
                }
                if (WebSiteTemplateConfig.WebSite_OpenMainCache)
                    memoryCache.Set(WebSiteConfig.SYSTEM_SLIDERMEMORYKEY_STRING, OutHtml);
                break;
            }
			if (mc.Count==0)
            {
                return html;
            }
            return Regex.Replace(html, "@Slider_Start[.\\s\\S]*@Slider_End", OutHtml.ToString(), RegexOptions.IgnoreCase);
        }


        /// <summary>
        /// 加载顶部导航菜单
        /// </summary>
        /// <returns></returns>
        public async Task<string> LoadHeaderNavigationInfo(string html)
        {
            if (WebSiteTemplateConfig.WebSite_OpenTemplateCache)
            {
                var memoryDataInfo = memoryCache.Get(WebSiteConfig.SYSTEM_NAVIGATIONMEMORYKEY_STRING);
                if (memoryDataInfo != null)
                {
                    return Regex.Replace(html, "@Navigation_Start[.\\s\\S]*@Navigation_End", memoryDataInfo.ToString(), RegexOptions.IgnoreCase);
                }
            }
            List<tc_navigation> navigationInfo = await navigationService.GetIsUseList();

            string OutHtml = string.Empty;
            //MatchCollection mc_one = Regex.Matches(html, "(?<=(@Navigation\\())[.\\s\\S]*?(?=(\\)))");
            MatchCollection mc_one = Regex.Matches(html, "(?<=(@Navigation_Start))[.\\s\\S]*?(?=(@Navigation_End))");
            foreach (Match m in mc_one)
            {
                var arr = m.Value.Split(",",StringSplitOptions.RemoveEmptyEntries);
                var parmList = new List<string>() {"","",""};
                for(int i = 0; i< arr.Length;i++)
                {
                    parmList[i] = arr[i];
                }

                StringBuilder one_li_list_html = new StringBuilder();
                MatchCollection mc_one_li = Regex.Matches(html, "(?<=(@Nav_Foreach_Start))[.\\s\\S]*?(?=(@Nav_Foreach_End))");
                
                foreach (Match one_li in mc_one_li)
                {
                    foreach (var navInfo in navigationInfo.Where(x=>x.parentId==-1))
                    {
                        var subNavInfo = navigationInfo.Where(x => x.parentId == navInfo.id);
                        var temp = one_li.Value.Replace("@Nav_Url", navInfo.menuUrl).Replace("@Nav_Name", navInfo.name);
                        if (subNavInfo.Any())
                        {
                            temp = temp.Replace("@Nav_HasChildren", parmList[2]);
                        }
                        else
                        {
                            temp = temp.Replace("@Nav_HasChildren", "");
                        }
                            
                        
                        if (subNavInfo.Any())
                        {
                            StringBuilder two_li_list_html = new StringBuilder();
                            MatchCollection mc_two_li = Regex.Matches(html, "(?<=(@Nav_Foreach_Sub_Start))[.\\s\\S]*?(?=(@Nav_Foreach_Sub_End))");
                            foreach (Match two_li in mc_two_li)
                            {
                                foreach (var subInfo in subNavInfo)
                                {
                                    two_li_list_html.Append(two_li.Value.Replace("@Nav_Url", subInfo.menuUrl).Replace("@Nav_Name", subInfo.name));
                                }
                            }
                            var sub = Regex.Replace(parmList[1], "@Nav_Foreach_Sub_Start[.\\s\\S]*@Nav_Foreach_Sub_End", two_li_list_html.ToString(), RegexOptions.IgnoreCase);
                            temp = temp.Replace("@Nav_Sub", sub);
                        }
                        else
                        {
                            temp = temp.Replace("@Nav_Sub", "");
                        }
                        one_li_list_html.Append(temp);
                    }
                    
                   
                }



                var NavOutHtml = Regex.Replace(parmList[0], "@Nav_Foreach_Start[.\\s\\S]*@Nav_Foreach_End", one_li_list_html.ToString(), RegexOptions.IgnoreCase);
                OutHtml = Regex.Replace(html, "@Navigation_Start[.\\s\\S]*@Navigation_End", NavOutHtml, RegexOptions.IgnoreCase);
                if (WebSiteTemplateConfig.WebSite_OpenTemplateCache)
                    memoryCache.Set(WebSiteConfig.SYSTEM_NAVIGATIONMEMORYKEY_STRING, NavOutHtml);
                break;
            }
            if (mc_one.Count==0)
            {
                OutHtml = html;
            }
            return OutHtml;
        }


        /// <summary>
        /// 加载所有模板页面
        /// </summary>
        /// <returns></returns>
        public async Task GetTemplateHtmlPages()
        {
            string webRootPath = environment.WebRootPath;
            var currentName = memoryCache.Get(WebSiteConfig.WEBSITE_TEMPLATENAME_STRING);

            var filePath = webRootPath + WebSiteConfig.WEBSITE_TEMPLATENAME_PATH + currentName + "/";
            foreach (var item in Core.Config.WebSiteTemplateConfig.GetTemplatePages())
            {
                //开启缓存情况下，模板内容不为空就不用重复获取
                if (WebSiteTemplateConfig.WebSite_OpenTemplateCache&& !string.IsNullOrEmpty(item.htmlContent))
                    continue;
                item.htmlContent = await ReadTemplateFile(filePath + item.name);
            }

        }


        /// <summary>
        /// 读取模板文件
        /// </summary>
        /// <returns></returns>
        private async Task<string> ReadTemplateFile(string path)
        {
            var fileContent = string.Empty;
            //判断文件是否存在
            if (System.IO.File.Exists(path))
            {
                fileContent = await System.IO.File.ReadAllTextAsync(path);
            }
            else
            {
                using (System.IO.File.Create(path)) //必须释放
                {

                }
            }
            return fileContent;
        }


    }
}
